/////////////////////////////////////////////////////////////////////////////////////////
// Luminary Micro / Circuit Cellar 2007 Design Contest
// Entry LM1732
//
// Main File
/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////
// 24 bits color BMP File Management
/////////////////////////////////////////////////////////////////////////////////////////
// Pixel (x,y) in cartesian coordinate to BMP file offset position
// offset = header_size + 3*x color_pixels + (bmp_height-1 - y) * bmp_width * 3 color_pixels
// offset = 54 + 3x + (479 - y) * 640 * 3
// offset = 3x - 1920y + 919734


////////////////////////////////////////////////////////////////////////////
// INCLUDES
////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdlib.h>											// rand()
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "gpio.h"
#include "interrupt.h"
#include "sysctl.h"
#include "timer.h"
#include "ssi.h"
#include "../osram96x16.h"
#include "globals.h"
#include "mmc.h"
#include "ff.h"


////////////////////////////////////////////////////////////////////////////
// GET_FATTIME
////////////////////////////////////////////////////////////////////////////
DWORD get_fattime ()
{
//	return	((2007UL-1980) << 25)	// Year = 2006
	return	(((rand() % 2007) - 1979) << 25)	// Year = 2006
			| (2UL << 21)			// Month = Feb
			| (9UL << 16)			// Day = 9
			| (13U << 11)			// Hour = 13
			| (0U << 5)				// Min = 00
			| (0U >> 1);			// Sec = 00
}


////////////////////////////////////////////////////////////////////////////
// TIMER0INTHANDLER
// Used for SD card low level function timings, is also used to update SD
// card flags like write protection and disk inserted
////////////////////////////////////////////////////////////////////////////
void Timer0IntHandler(void)
{    
	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);			// Clear the timer interrupt
	disk_timerproc();										// Low level disk I/O function
}


////////////////////////////////////////////////////////////////////////////
// MAIN
////////////////////////////////////////////////////////////////////////////
int main(void)
{
FATFS fs;
FIL fbmp;													// BMP file
FRESULT result;
WORD len;
// Could have used FIL buffer or just one Buffer, but LM3S811 has plenty of memory...
BYTE Buffer[512];											// General file write buffer

int i;
long offse;

	
    // Set the clocking to run at 50MHz from the PLL
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ);
	//SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_3_57MHZ);		// overclock to #69 MHz

    // Enable the peripherals used by the application
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI);

    // Configure LED, push button
    GPIODirModeSet(GPIO_PORTC_BASE, PUSH_BUTTON, GPIO_DIR_MODE_IN);
    GPIODirModeSet(GPIO_PORTC_BASE, USER_LED, GPIO_DIR_MODE_OUT);
    GPIOPinWrite(GPIO_PORTC_BASE, USER_LED, 0);

	// SPI
	SSIDisable(SSI_BASE);
	GPIODirModeSet(SD_PORT, SD_CS, GPIO_DIR_MODE_OUT);
	GPIOPinWrite(SD_PORT, SD_CS, SD_CS);							// SD Card not selected
	GPIOPinTypeSSI(SD_PORT, SD_CLK | SD_DI | SD_DO);
	// Configure and enable the SPI module
	SSIConfig(SSI_BASE, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 12500000, 8);
	//SSIConfig(SSI_BASE, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 25000000, 8);
	SSIEnable(SSI_BASE);

	// Configure other SD Card GPIOs as required
    GPIODirModeSet(SOCKPORT, SOCKWP, GPIO_DIR_MODE_IN);
	GPIODirModeSet(SOCKPORT, SOCKINS, GPIO_DIR_MODE_IN);
	GPIODirModeSet(GPIO_PORTB_BASE, HOST_CS, GPIO_DIR_MODE_IN);
	GPIODirModeSet(GPIO_PORTC_BASE, HOST_EN, GPIO_DIR_MODE_OUT);
	HOST_DISABLE;													// Isolate Host from SD carc
	for(offse=0; offse<20000000; offse++);

    // Configure timer0 to generate an IRQ every 10ms
	TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
    TimerLoadSet(TIMER0_BASE, TIMER_A, (SysCtlClockGet()/100)-1);
	TimerEnable(TIMER0_BASE, TIMER_A);
	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	IntEnable(INT_TIMER0A);

    // Initialize the OSRAM OLED display.
    OSRAMInit(true);

    // Enable processor interrupts.
    IntMasterEnable();

	memset(&fs, 0, sizeof(FATFS));
	FatFs = &fs;	

	result = f_open(&fbmp, "test1.txt", FA_CREATE_ALWAYS | FA_WRITE );
	if ( result != FR_OK ) {
		switch (result) {
		case FR_NO_FILE :
		    OSRAMStringDraw("FR_NO_FILE", 0, 0);
			break;
		case FR_NO_PATH :
			OSRAMStringDraw("FR_NO_PATH", 0, 0);
			break;
		case FR_INVALID_NAME :
			OSRAMStringDraw("FR_INVALID_NAME", 0, 0);
			break;
		case FR_DENIED :
			OSRAMStringDraw("FR_DENIED", 0, 0);
			break;
		case FR_NOT_READY :
			OSRAMStringDraw("FR_NOT_READY", 0, 0);
			break;
		case FR_WRITE_PROTECTED :
			OSRAMStringDraw("FR_WRITE_PROTECTED", 0, 0);
			break;
		case FR_RW_ERROR :
			OSRAMStringDraw("FR_RW_ERROR", 0, 0);
			break;
		case FR_INCORRECT_DISK_CHANGE :
			OSRAMStringDraw("FR_INCORRECT_DISK_CHANGE", 0, 0);
			break;
		case FR_NOT_ENABLED :
			OSRAMStringDraw("FR_NOT_ENABLED", 0, 0);
			break;
		case FR_NO_FILESYSTEM :
			OSRAMStringDraw("FR_NO_FILESYSTEM", 0, 0);
			break;
		default :
			OSRAMStringDraw("not openw", 0, 0);
			break;	
		}
		for(offse=0; offse<5000000; offse++);
	}
	for (i=0; i<1024*5; i++) {
		result = f_write(&fbmp, Buffer, 512, &len);
		if (len != 512) {
			OSRAMStringDraw("BMP Data Write0 failed", 0, 0);
			for(offse=0; offse<5000000; offse++);
		}
	}	// write file
	result = f_close( &fbmp );
	if (result != FR_OK) OSRAMStringDraw("not closed", 0, 0);
	else OSRAMStringDraw("closed ok              ", 0, 0);
	while(1);
		
}


